<script setup>
import {computed, inject, onMounted, reactive, ref, watch} from "vue";
import {Debounce} from "./debounce";
import {getTreeNodeById} from "./TreeHelper";
import DropdownSearch from "./DropdownSearch.vue";
//================================================【组件通信】============================================================
//=======================================================【传入】
//请求工具
const context = inject('context')
//父组件传递的数据
const props = defineProps({
  nrDateParam:{
    type:String,
    required:true
  },
  nrUnitCode:{
    type:String,
    required:true
  },
  nrUnitName:{
    type:String,
    required:true
  },
  dataCheckResType:{
    type:String,
    required:false,
    default:''
  },
  //单位选择器配置项
  configs: {
    type: Object,
    required: false,
    default: function() {
      let defaultConfigs = {};
      defaultConfigs.switchs={
        'allUnit':true,
        'sharedUnit':true,
        'unSharedUnit':true
      };
      return defaultConfigs;
    }
  }
});
//=======================================================【传出】
const emit = defineEmits(['update:nrUnitCode','update:nrUnitName'])
//================================================【公用相关】============================================================
//请求加载中
const isLoading = ref(false)
//状态控制相关
//控制展示类型 0：全部单位（树形）  1：未分摊单位（表格）  2：已分摊单位（表格）
const showType = ref(0)
//搜索内容
const searchKeyWord = ref('')
//树形数据
const treeData = reactive([])


//清空单位信息
function cleanUnitInfo() {
  setDataCheckReqParam('','')
}
//设置数据请求参数
function setDataCheckReqParam(code,name) {
  emit('update:nrUnitCode',code)
  emit('update:nrUnitName',name)
}
/**
 * 加载展示数据
 * @param isInit    是否为初始化
 */
function loadShowData(isInit) {
  let loadFactor = 0;

  //加载量
  if (isInit) {
    tableShowData.splice(0, tableShowData.length);
    loadFactor = 500;
  } else {
    loadFactor = 100;
  }
  //载入
  if (tableAllData.length > loadFactor) {
    tableShowData.push(...tableAllData.splice(0, loadFactor));
  } else {
    tableShowData.push(...tableAllData.splice(0, tableAllData.length));
  }
}
//================================================【组件属性】============================================================
//下拉菜单开关
const switchs = computed(() => {
  return props.configs['switchs'];
})
const curUnitCode = ref('')
watch(()=>props.nrUnitCode,(newValue)=>{
  curUnitCode.value = newValue
})
const curUnitName = ref('')
watch(()=>props.nrUnitName,(newValue)=>{
  curUnitName.value = newValue
})
watch(()=>props.nrDateParam,()=>{
  //当时期参数改变时
  cleanUnitInfo()
  changeShowType('allUnit')
})
/**
 * 状态监视器
 *
 *          全部单位   展示树形            1
 *                   搜索表格            2
 *
 *         未分摊单位  展示表格            3
 *                   搜索表格            4
 *
 *         已分摊单位  展示表格           5
 *                   搜索表格           6
 */
const stateMonitor = computed(() => {
  if (showType.value === 0)
    if (searchKeyWord.value === '')
      return 1
    else
      return 2
  else if (showType.value === 1)
    if (searchKeyWord.value === '')
      return 3
    else
      return 4
  else if (showType.value === 2)
    if (searchKeyWord.value === '')
      return 5
    else
      return 6
  else
    return '错误'
})

//触发搜索
watch(searchKeyWord, (newValue) => {
  search(newValue);
})
//监听数据审核结果类型
watch(()=>props.dataCheckResType, (newValue) => {
    const curNode = getTreeNodeById(treeData, curUnitCode.value)
    if (curNode) {
      if (newValue === 'CALCULATING') {
        curNode.validateStatusEnum = 'PROCESS';
      } else if (newValue === 'SUCCESS') {
        curNode.validateStatusEnum = 'SUCCESS';
      } else if (newValue === 'WARNING') {
        curNode.validateStatusEnum = 'WARNING';
      } else if (newValue === 'ERROR') {
        curNode.validateStatusEnum = 'ERROR';
      } else {
        curNode.validateStatusEnum = 'OTHER';
      }
    }


    const findedIndex = tableShowData.findIndex(preFindItem => {
      return preFindItem.code === curUnitCode.value
    })

    if (findedIndex !== -1) {
      if (newValue === 'CALCULATING') {
        tableShowData[findedIndex].validateStatusEnum = 'PROCESS';
      } else if (newValue === 'SUCCESS') {
        tableShowData[findedIndex].validateStatusEnum = 'SUCCESS';
      } else if (newValue === 'WARNING') {
        tableShowData[findedIndex].validateStatusEnum = 'WARNING';
      } else if (newValue === 'ERROR') {
        tableShowData[findedIndex].validateStatusEnum = 'ERROR';
      } else {
        tableShowData[findedIndex].validateStatusEnum = 'OTHER';
      }
    }
})
//================================================【普通方法】============================================================
function search(newValue) {
  //【注意】：状态已经改变，回补应有效果
  isLoading.value = true

  if (stateMonitor.value === 1) {
    //状态1 无关跳转 不需要额外操作
    isLoading.value = false
  }

  if (stateMonitor.value === 2) {
    Debounce(
        context.getPlugin('http').get(`abc/unit/fuzzyMatch/${props.nrDateParam}?searchKey=${newValue}`)
            .then(({data}) => {
              panelAllData.splice(0, panelAllData.length, ...data.matchedList)
              isLoading.value = false
            }), 300)()
  }

  if (stateMonitor.value === 3) {
    tableAllData.splice(0, tableAllData.length, ...unSharedUnitList)
    loadShowData(true, false)
    //状态3 无关跳转 不需要额外操作
    isLoading.value = false

  }

  if (stateMonitor.value === 4) {
    const tempArr = unSharedUnitList.filter(preFilterItem => {
      return preFilterItem.name.indexOf(newValue) !== -1
          ||
          preFilterItem.code.indexOf(newValue.trim().toLowerCase()) !== -1
          ||
          preFilterItem.code.indexOf(newValue.trim().toUpperCase()) !== -1
    })

    panelAllData.splice(0, panelAllData.length, ...tempArr)
    isLoading.value = false
  }


  if (stateMonitor.value === 5) {
    tableAllData.splice(0, tableAllData.length, ...sharedUnitList)
    loadShowData(true, false)
    //状态5 无关跳转 不需要额外操作
    isLoading.value = false
  }

  if (stateMonitor.value === 6) {
    const tempArr = sharedUnitList.filter(preFilterItem => {
      return preFilterItem.name.indexOf(newValue) !== -1
          ||
          preFilterItem.code.indexOf(newValue.trim().toLowerCase()) !== -1
          ||
          preFilterItem.code.indexOf(newValue.trim().toUpperCase()) !== -1
    })

    panelAllData.splice(0, panelAllData.length, ...tempArr)
    isLoading.value = false
  }
}
//==================================================================【搜索面板】
//面板全部数据
const panelAllData = reactive([])
//面板项点击
function searchPanelItemClick(clickItem) {
//三类搜索表格 状态还未改变 预设应有效果
  // 状态2（全部单位 搜索表格）   有关跳转
  if (stateMonitor.value === 2){

    //点击搜索表格 此时确认需要返回展示树形，展示树形原有高亮取消
    curUnitCode.value !== ''?
        getTreeNodeById(treeData,curUnitCode.value).selected = false
        :
        null

    setDataCheckReqParam(clickItem.code,clickItem.name)
    context.getPlugin('http').get(`abc/unit/getTracePath/${props.nrDateParam}/${clickItem.code}`).then(({data}) => {
      expandPath(data,0)
    })

  }
  // 状态4（未分摊单位 搜索表格） 有关跳转
  if (stateMonitor.value === 4){
    const findedItem = unSharedUnitList.find(preFindItem => {
      return preFindItem.code === clickItem.code
    })
    tableAllData.splice(0, tableAllData.length, ...unSharedUnitList)
    loadShowData(true,false)

    tableLineClick(findedItem,true)

    setTimeout(() => {
      const tableScrollIntoViewTarget = document.getElementsByClassName('tableScrollIntoViewTarget')[0]
      if (tableScrollIntoViewTarget)
        tableScrollIntoViewTarget.scrollIntoView({
          behavior: 'smooth', // 平滑滚动
          block: 'center'
        });
    }, 400)
  }

  // 状态6 (已分摊单位 搜索表格)  有关跳转
  if (stateMonitor.value === 6){
    const findedItem = sharedUnitList.find(preFindItem => {
      return preFindItem.code === clickItem.code
    })
    tableAllData.splice(0, tableAllData.length, ...sharedUnitList)
    loadShowData(true,false)

    tableLineClick(findedItem,true)

    setTimeout(() => {
      const tableScrollIntoViewTarget = document.getElementsByClassName('tableScrollIntoViewTarget')[0]
      if (tableScrollIntoViewTarget)
        tableScrollIntoViewTarget.scrollIntoView({
          behavior: 'smooth', // 平滑滚动
          block: 'center'
        });
    }, 400)
  }

}
//==================================================================【下拉菜单相关】
//全部单位选中
const allUnitSelected = ref(true)
//已分摊单位选中
const sharedUnitSelected = ref(false)
//未分摊单位选中
const unSharedUnitSelected = ref(false)
//下拉选项触发事件
function changeShowType(dropDownName) {
  //置空 搜索关键字
  searchKeyWord.value = ''
  //如果类型改变，选择的表格项初始化
  tableShowData.map(preMapItem => preMapItem.highlight = false)
  cleanUnitInfo()
  isLoading.value = true
  if (dropDownName === 'allUnit') {
    showType.value = 0
    setDropDownItemSelected('allUnit')
    initDataTree().then(()=>{
      isLoading.value = false
    })
  } else if (dropDownName === 'unSharedUnit') {
    showType.value = 1
    setDropDownItemSelected('unSharedUnit')
    context.getPlugin('http').get(`abc/unit/all/${props.nrDateParam}`).then(({data}) => {
      unSharedUnitList.splice(0, unSharedUnitList.length, ...data.allUnitList.unSharedUnitList)
      tableAllData.splice(0, tableAllData.length, ...unSharedUnitList)
      loadShowData(true,false)
      isLoading.value = false
    })
  } else if (dropDownName === 'sharedUnit') {
    showType.value = 2
    setDropDownItemSelected('sharedUnit')
    context.getPlugin('http').get(`abc/unit/all/${props.nrDateParam}`).then(({data}) => {
      sharedUnitList.splice(0, sharedUnitList.length, ...data.allUnitList.sharedUnitList)
      tableAllData.splice(0, tableAllData.length, ...sharedUnitList)
      loadShowData(true,false)
      isLoading.value = false
    })
  }
}
//控制下拉菜单的选中
function setDropDownItemSelected(itemTitle) {
  allUnitSelected.value = false
  sharedUnitSelected.value = false
  unSharedUnitSelected.value = false

  switch (itemTitle) {
    case 'allUnit':
      allUnitSelected.value = true
      break;
    case 'sharedUnit':
      sharedUnitSelected.value = true
      break;
    case 'unSharedUnit':
      unSharedUnitSelected.value = true
      break;
  }
}
//==================================================================【树形相关】
//树形元素
const unitTreeElRef = ref()
//获取 单位树形 根节点
function initDataTree() {
  return new Promise((resolve) => {
    isLoading.value = true
    context.getPlugin('http').get(`abc/unit/children/${props.nrDateParam}/null`)
        .then(({data}) => {
          treeData.splice(0, treeData.length, ...data.childrenUnitList)
          isLoading.value = false
          resolve()
        })
  })
}

//异步加载树形节点
function loadData(item, pathIndex, path) {
  return new Promise((resolve) => {
    context.getPlugin('http').get(`abc/unit/children/${props.nrDateParam}/${item.id}`).then(({data}) => {

      //单一加载、逐级加载  公用
      let subNodeList = data.childrenUnitList
      const nodeDataArr = []
      for (let i = 0; i < subNodeList.length; i++) {
        const nodeData = subNodeList[i];

        if (!nodeData.isLeaf) {
          nodeData.expand = false
        } else {
          nodeData.expand = true
        }
        nodeDataArr.push(nodeData)
      }
      if (!item.children) {
        item.children = reactive([])
      }
      //根据已有溯源路径逐级展开时添加子节点信息
      item.children.push(...reactive(nodeDataArr))
      //手动点击单个树形节点加载该节点直接下级树形数据
      resolve(nodeDataArr)

      item.expand = true


      //逐级加载模式
      if (pathIndex !== undefined)
        expandPath(path, pathIndex + 1)
    })
  })
}

/**
 * 根据路径展开
 * @param {*} path          追溯路径
 * @param {*} pathIndex     准备处理的路径节点
 */
function expandPath(path, pathIndex) {
  // console.log('查看自动展开')
  if (pathIndex < path.length) {
    const nodeId = path[pathIndex]
    const targetNode = getTreeNodeById(treeData, nodeId)
    //不是 最终路径节点 则处理下一个路径节点
    if (pathIndex !== path.length - 1) {
      // 子节点存在
      if (targetNode.children) {
        targetNode.expand = true
        expandPath(path, ++pathIndex)
        // 子节点不存在则加载子节点
      } else {
        loadData(targetNode, pathIndex, path)
      }

      //是 最终路径节点 选中节点
    } else {
      targetNode.selected = true
      //自动滚动，使选中项可见
      setTimeout(() => {
        const treeScrollIntoViewTarget = document.getElementsByClassName('treeScrollIntoViewTarget')[0]
        if (treeScrollIntoViewTarget)
          treeScrollIntoViewTarget.scrollIntoView({
            behavior: 'smooth', // 平滑滚动
            block: 'center'
          });
      }, 400)
    }
  }
}

//点击选择树形数据
function treeNodeClick({id,title}) {
  //当前选择树形节点不为空时（当点击已选择节点，此时选择节点数组为空）
  if (unitTreeElRef.value.getSelectedNodes().length > 0) {
    setDataCheckReqParam(id,title)
  } else {
    cleanUnitInfo()
  }
}
//==================================================================【表格相关】
//表格表头信息
const tablecolumns = reactive([
  {
    title: '',
    slot: 'statusSlot',
    width: 35
  },
  {
    title: '单位代码',
    key: 'code',
    align: 'left',
    poptip: true
  },
  {
    title: '单位名称',
    key: 'name',
    align: 'left',
    poptip: true,
  },
])
//表格显示数据
const tableShowData = reactive([])
//表格全部数据
const tableAllData = reactive([])
//未分摊数据
const unSharedUnitList = reactive([])
//已分摊数据
const sharedUnitList = reactive([])
//表格点击
function tableLineClick(curLineItem,byCode) {
  //表格只允许同一时间显示一条高亮行
  tableShowData
      .filter(preFilterItem => {
        return preFilterItem.code !== curLineItem.code
      })
      .map(preMapItem => preMapItem.highlight = false)

  byCode ?
      //从搜索面板点击通过代码调用跳转至表格项时，高亮效果需要手动设置
      tableShowData
          .filter(preFilterItem => {
            return preFilterItem.code === curLineItem.code
          })
          .map(preMapItem => preMapItem.highlight = true)
      &&
      setDataCheckReqParam(curLineItem.code, curLineItem.name)
      :
      curLineItem.highlight ?
          setDataCheckReqParam(curLineItem.code, curLineItem.name)
          :
          cleanUnitInfo()
}
//表格懒加载
function handleMiddleContentScroll(event) {
  const target = event.target;
  if (target instanceof HTMLElement) {
    const scrollTop = target.scrollTop;
    // 计算是否滚动到90%的位置
    const threshold = target.scrollHeight * 0.9;
    if (scrollTop >= threshold && scrollTop !== Math.floor(threshold)) {
      loadShowData(false,false)
    }
  }
}
//================================================【生命周期】============================================================
onMounted(() => {
  initDataTree()
})
</script>

<template>
  <div style="width: 100%;height: 100%">
    <div class="topSearch">
      <DropdownSearch
          style="width: 90%"
          v-model:searchKeyWord="searchKeyWord"
          :panelAllData="panelAllData"
          @searchPanelItemClick="searchPanelItemClick">
        <template #dropDownItemTemp="{itemData}">
          <slot name="dropDownItem" :item="itemData"></slot>
        </template>
      </DropdownSearch>
      <j-dropdown
          hiden-arrow
          style="width: 10%"
          placement="bottom-start"
          @click="changeShowType">
        <j-button style="width: 100%;padding: 0px" icon="icon-filter"></j-button>
        <template #list>
          <j-dropdown-menu>
            <j-dropdown-item v-if="switchs.allUnit" name="allUnit" :selected="allUnitSelected">所有单位</j-dropdown-item>
            <j-dropdown-item v-if="switchs.sharedUnit" name="sharedUnit" :selected="sharedUnitSelected">已分摊单位</j-dropdown-item>
            <j-dropdown-item v-if="switchs.unSharedUnit" name="unSharedUnit" :selected="unSharedUnitSelected">未分摊单位</j-dropdown-item>
          </j-dropdown-menu>
        </template>
      </j-dropdown>
    </div>
    <div class="middleContent"  @scroll="handleMiddleContentScroll">
      <j-spin :show="isLoading" :wrapper-style="{ height: '100%'}" :style="{ height: '100%' }">
        <div v-if="stateMonitor === 1 || stateMonitor === 2">
          <j-tree
              ref="unitTreeElRef"
              v-model:data="treeData"
              select-type="check"
              :load-data="loadData"
              @select="treeNodeClick"
          >
            <template #node="node">
              <slot name="treeNode" :node="node"></slot>
            </template>
          </j-tree>
        </div>

        <div v-if="stateMonitor !== 1 && stateMonitor !== 2" style="height: 100%">
          <j-table style="height: 100%"
                   :columns="tablecolumns"
                   :data="tableShowData"
                   @row-click="tableLineClick"
                   highlight>
            <template #statusSlot="{row}">
              <slot name="tableRowStatus" :row="row"></slot>
            </template>
          </j-table>
        </div>
      </j-spin>
    </div>
  </div>
</template>

<style scoped>
.topSearch {
  width: 100%;
  display: flex;
  flex-direction: row;
}
.topSearch > :first-child > :first-child {
  display: block;
}
.middleContent {
  width: 100%;
  height: calc(100% - 32px);
  overflow-y: auto;
}
</style>
